Refactor ImpactedPackage and ResolvedPackage - #219
Conversation
|
@haikoschol I have pushed a commit to stop using I think I can acheive the same results as the one with properties, if I could remove duplicates of model instances(these dont yet have pk ) from a list. Do you have any ideas to do that ? |
Have you tried the naive approach of just iterating the list and comparing all fields? |
That is a valid approach, I instead went with creating a dataclass and put it into a set and then instantiate model instances. I've tested it for Could you suggest an OK name for the dataclass ? |
…ackage_Relation Changes are made in import_runner.py to refactore the models. Other major changes in import_runner.py is to change the _process_updated_advisories method to use less db queries and increase performance by several times. Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
71eacc8 to
5fcb5ea
Compare
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
de105b8 to
35280ff
Compare
pombredanne
left a comment
There was a problem hiding this comment.
Thanks!
I commented mostly here, but I think I would still prefer concrete types (e.g. a real ImpactedPackage and ResolvedPackage class) that a generic type and an attribute.
|
|
||
|
|
||
| @dataclasses.dataclass(frozen=True) | ||
| class VulnerabilityReference_inserter: |
There was a problem hiding this comment.
Please use TitleCase for classes, not a mix of Title_and_snake case
|
|
||
|
|
||
| @dataclasses.dataclass(frozen=True) | ||
| class PackageRelatedVulnerability_inserter: |
There was a problem hiding this comment.
Same as above and elsewhere: stick to TitleCase for classes and snake_case elsewhere
|
|
||
| def _process_updated_advisories(data_source: DataSource) -> None: | ||
| """ | ||
| TODO: Break this method into smaller functions |
There was a problem hiding this comment.
Does this comment still applies?
| bulk_create_vuln_pkg_refs = set() | ||
| for batch in data_source.updated_advisories(): | ||
| for advisory in batch: | ||
|
|
| vuln, vuln_created, advisory.resolved_package_urls, is_vulnerable=False) | ||
| bulk_create_vuln_pkg_refs.update(inew_refs.union(rnew_refs)) | ||
|
|
||
| models.VulnerabilityReference.objects.bulk_create( |
There was a problem hiding this comment.
What benefit do you get from calling bulk_create vs creating as you go above?
There was a problem hiding this comment.
We had this discussion in the chat. I think this is justified
| packages = models.Package.objects.bulk_create(packages) | ||
| impacted: List[PackageURL], | ||
| resolved: List[PackageURL] | ||
| ) -> Tuple[Dict[PackageURL, int], Dict[PackageURL, int]]: |
There was a problem hiding this comment.
Have you enabled type checking at least in the CI?
Otherwise, type hints are not always helpful and if the types are not checked somehow, they can be misleading and i most case they are not conducive to improve readability... So let's not get carried away with type hints for the sake of them. Instead enter a ticket so we can discuss and plan for their possible usage
There was a problem hiding this comment.
Agreed. In the CI it would be something along the lines of running a simple Mypy check right ? That probably won't be much of pain.
IMHO using typing help in most cases to atleast know what's going in and out, way better than comments, but that's just my opinion. Looking at this again I feel rather ashamed of this case though, it really seems I've used typing in a rather cryptic way.
Reverting this method, to the old one which was readable.
| impacted_packages[purl] = pkg | ||
| elif purl in resolved: | ||
| resolved_packages[purl] = pkg | ||
| impacted_packages = dict( |
There was a problem hiding this comment.
I understand the zip here, but is there a simpler way to get there?
I am always nervous when we start using "parallel lists" to later zip them.
There was a problem hiding this comment.
Reverted to previous approach, which was more readable.
| vulnerabilities: Set[models.Vulnerability], | ||
| impacted_packages: Dict[PackageURL, models.Package], | ||
| resolved_packages: Dict[PackageURL, models.Package], | ||
| impacted_packages: Dict[PackageURL, int], |
There was a problem hiding this comment.
Overenginnering/pre-mature optimization . The idea was to use Dict[PackageURL, int] where the int is pk of Package , to save some memory because these dictionaries would grow big very fast. Carrying the Objects is way more expensive than pks so I had used it .
Reverting this.
| ip = models.PackageRelatedVulnerability( | ||
| vulnerability=vuln, | ||
| package=p, | ||
| package_id=p, |
There was a problem hiding this comment.
is p a package or a package_id?
There was a problem hiding this comment.
Reverting this. p is a package.
| p = _package_url_to_package(resolved_purl) | ||
| p.save() | ||
| resolved_packages[resolved_purl] = p | ||
| resolved_packages[resolved_purl] = p.id |
There was a problem hiding this comment.
What are the benefits of using ids vs objects there?
There was a problem hiding this comment.
As mentioned above this is :
Overenginnering/pre-mature optimization . The idea was to use Dict[PackageURL, int] where the int is pk of Package , to save some memory because these dictionaries would grow big very fast. Carrying the Objects is way more expensive than pks so I had used it .
Reverting this.
|
@sbs2001 after our discussion I am not fine with the merging of ImpactedPackage and ResolvedPackage in a single model. :) |
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
60b63f8 to
189582d
Compare
pombredanne
left a comment
There was a problem hiding this comment.
I added some more comments
| for batch in data_source.updated_advisories(): | ||
| for advisory in batch: | ||
| vuln, _ = _get_or_create_vulnerability(advisory) | ||
| def _create_vulnerability_and_references(advisory: Advisory): |
|
At this stage since this is blocking further updates, I am merging it with the caveats noted otherwise... 👍 |
Changes are made in import_runner.py to refactor the models.
Other major changes in import_runner.py is to change the _process_updated_advisories
method to use less db queries and increase performance by several times.
Having a single table for these, fixes the following:
Issue 1 :
You can do this, which doesn't make any sense.
This is pure garbage, nothing can be interpreted from these entries.
With a single table + flag, we can use a unique_together=('vulnerability','package')
Issue 2 :
Updating the vulnerability status of a package is not possible due to cascade deletes.
Check https://github.com/nexB/vulnerablecode/blob/58d0376e7319d06387662cb393f3c39d9893088d/vulnerabilities/import_runner.py#L121 .
And also check for more details https://github.com/nexB/vulnerablecode/blob/58d0376e7319d06387662cb393f3c39d9893088d/vulnerabilities/tests/test_import_runner.py#L201
Signed-off-by: Shivam Sandbhor shivam.sandbhor@gmail.com